﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.DynamicData;
using System.Web.UI;
using System.Web.UI.WebControls;
using PD.DataAccess;

namespace PD.Web.DynamicData.FieldTemplates
{
    /// <summary>
    /// Represents the enumeration field template control.
    /// </summary>
    public partial class Enumeration_EditField : System.Web.DynamicData.FieldTemplateUserControl
    {
        /// <summary>
        /// The state machine map.
        /// </summary>
        private static IDictionary<TaskStatus, IEnumerable<TaskStatus>> stateMachine = new Dictionary<TaskStatus, IEnumerable<TaskStatus>>()
        {
            { TaskStatus.NotStarted, new List<TaskStatus> { TaskStatus.NotStarted, TaskStatus.InProgress, TaskStatus.WaitingOnSomeoneElse } },
            { TaskStatus.InProgress, new List<TaskStatus> { TaskStatus.InProgress, TaskStatus.Approved, TaskStatus.Rejected, TaskStatus.WaitingOnSomeoneElse } },
            { TaskStatus.WaitingOnSomeoneElse, new List<TaskStatus> { TaskStatus.WaitingOnSomeoneElse, TaskStatus.InProgress } },
            { TaskStatus.Approved, new List<TaskStatus> { TaskStatus.Approved } },
            { TaskStatus.Rejected, new List<TaskStatus> { TaskStatus.Rejected } },
        };

        /// <summary>
        /// The type of the enum.
        /// </summary>
        private Type enumType;

        /// <summary>
        /// Gets the data control that handles the data field in a field template.
        /// </summary>
        /// <returns>A data control that handles the data field in a field template.</returns>
        public override Control DataControl
        {
            get
            {
                return this.DropDownList1;
            }
        }

        /// <summary>
        /// Gets the type of the enum.
        /// </summary>
        /// <value>
        /// The type of the enum.
        /// </value>
        private Type EnumType
        {
            get
            {
                if (this.enumType == null)
                {
                    this.enumType = Column.GetEnumType();
                }

                return this.enumType;
            }
        }

        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.DropDownList1.ToolTip = this.Column.Description;

            if (this.DropDownList1.Items.Count == 0)
            {
                this.PopulateListControl(this.DropDownList1);
                foreach (ListItem item in this.DropDownList1.Items)
                {
                    item.Text = Regex.Replace(item.Text, "(\\B[A-Z])", " $1");
                }

                if (this.Mode == DataBoundControlMode.Insert || !this.Column.IsRequired)
                {
                    this.DropDownList1.Items.Insert(0, new ListItem("[Not Set]", string.Empty));
                }
            }

            this.SetUpValidator(this.RequiredFieldValidator1);
            this.SetUpValidator(this.DynamicValidator1);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.DataBinding"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
        protected override void OnDataBinding(EventArgs e)
        {
            base.OnDataBinding(e);

            if (this.Mode == DataBoundControlMode.Edit && this.FieldValue != null)
            {
                if (this.FieldValue != null)
                {
                    string selectedValueString = GetSelectedValueString();
                    ListItem item = this.DropDownList1.Items.FindByValue(selectedValueString);
                    if (item != null)
                    {
                        this.DropDownList1.SelectedValue = selectedValueString;
                        this.TryApplyStateMachine();
                    }
                }
            }

            this.TryReduceInvoiceStatuses();
        }

        /// <summary>
        /// Provides dictionary access to all data in the current row.
        /// </summary>
        /// <param name="dictionary">The dictionary that contains all the new values.</param>
        protected override void ExtractValues(IOrderedDictionary dictionary)
        {
            string value = this.DropDownList1.SelectedValue;
            if (value == string.Empty)
            {
                value = null;
            }

            dictionary[Column.Name] = this.ConvertEditedValue(value);
        }

        /// <summary>
        /// Tries the apply state machine.
        /// </summary>
        private void TryApplyStateMachine()
        {
            if (this.EnumType.FullName == typeof(TaskStatus).FullName)
            {
                TaskStatus selectedValue = (TaskStatus)int.Parse(this.DropDownList1.SelectedValue);
                IEnumerable<TaskStatus> availableStatuses = stateMachine[selectedValue];
                foreach (ListItem item in this.DropDownList1.Items)
                {
                    TaskStatus value = (TaskStatus)int.Parse(item.Value);
                    item.Enabled = availableStatuses.Contains(value);
                }
            }
        }

        /// <summary>
        /// Tries the reduce invoice statuses.
        /// </summary>
        private void TryReduceInvoiceStatuses()
        {
            if (this.EnumType.FullName == typeof(InvoiceStatus).FullName)
            {
                foreach (ListItem item in this.DropDownList1.Items)
                {
                    if (!string.IsNullOrEmpty(item.Value))
                    {
                        InvoiceStatus value = (InvoiceStatus)int.Parse(item.Value);
                        item.Enabled = value <= InvoiceStatus.Incorrect;
                    }
                }
            }
        }
    }
}
